using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using SeataNet.Core.Saga;
using System.Collections.Concurrent;

namespace SeataNet.Samples.BusinessService.Controllers
{
    /// <summary>
    /// 业务服务 - Saga 模式示例
    /// 演示与 Java Seata Saga 模式的兼容性
    /// </summary>
    [ApiController]
    [Route("api/[controller]")]
    public class BusinessController : ControllerBase
    {
        private readonly ILogger<BusinessController> _logger;
        private readonly OrderSagaService _orderSagaService;

        public BusinessController(
            ILogger<BusinessController> logger,
            OrderSagaService orderSagaService)
        {
            _logger = logger;
            _orderSagaService = orderSagaService;
        }

        /// <summary>
        /// 创建订单 - 使用 Saga 模式
        /// </summary>
        [HttpPost("create-order")]
        public async Task<IActionResult> CreateOrder([FromBody] CreateOrderSagaRequest request)
        {
            _logger.LogInformation("开始创建订单（Saga模式），订单号：{OrderId}", request.OrderId);

            try
            {
                var success = await _orderSagaService.CreateOrder(request);

                if (success)
                {
                    _logger.LogInformation("订单创建成功（Saga），订单号：{OrderId}", request.OrderId);
                    return Ok(new { Success = true, OrderId = request.OrderId });
                }
                else
                {
                    _logger.LogWarning("订单创建失败（Saga），订单号：{OrderId}", request.OrderId);
                    return BadRequest(new { Success = false, Message = "订单创建失败" });
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "订单创建异常（Saga），订单号：{OrderId}", request.OrderId);
                throw;
            }
        }
    }

    /// <summary>
    /// 订单 Saga 服务
    /// 对应 Java: @Service + @SagaTransactional
    /// </summary>
    public class OrderSagaService : SagaServiceBase
    {
        private readonly ILogger<OrderSagaService> _logger;
        private readonly IHttpClientFactory _httpClientFactory;

        // 模拟数据库
        private static readonly ConcurrentDictionary<string, OrderRecord> _orders = new();
        private static readonly ConcurrentDictionary<string, StockRecord> _stocks = new();
        private static readonly ConcurrentDictionary<string, AccountRecord> _accounts = new();

        public OrderSagaService(
            ILogger<OrderSagaService> logger,
            IHttpClientFactory httpClientFactory) : base(logger)
        {
            _logger = logger;
            _httpClientFactory = httpClientFactory;

            // 初始化测试数据
            _stocks.TryAdd("product001", new StockRecord { ProductId = "product001", Stock = 100 });
            _stocks.TryAdd("product002", new StockRecord { ProductId = "product002", Stock = 50 });
            _accounts.TryAdd("user001", new AccountRecord { UserId = "user001", Balance = 1000m });
        }

        /// <summary>
        /// 创建订单 - Saga 编排
        /// 对应 Java: @GlobalTransactional + @SagaTransactional
        /// </summary>
        [SagaTransactional(
            SagaName = "create-order-saga",
            Timeout = 60000,
            RetryPolicy = "Exponential"
        )]
        public async Task<bool> CreateOrder(CreateOrderSagaRequest request)
        {
            _logger.LogInformation("Saga 开始: 创建订单 - OrderId={OrderId}", request.OrderId);

            // ===== 步骤1：创建订单 =====
            var createOrderResult = await ExecuteStepAsync(
                stepName: "CreateOrder",
                executeAction: async () =>
                {
                    _logger.LogInformation("Saga Step 1: 创建订单记录 - OrderId={OrderId}", request.OrderId);

                    var order = new OrderRecord
                    {
                        OrderId = request.OrderId,
                        UserId = request.UserId,
                        ProductId = request.ProductId,
                        Quantity = request.Quantity,
                        Amount = request.Amount,
                        Status = "CREATED",
                        CreateTime = DateTime.UtcNow
                    };

                    _orders.TryAdd(request.OrderId, order);
                    _logger.LogInformation("订单记录已创建：{OrderId}", request.OrderId);

                    return order;
                },
                compensateAction: async (data) =>
                {
                    _logger.LogWarning("Saga Compensation 1: 删除订单记录 - OrderId={OrderId}", request.OrderId);

                    if (_orders.TryRemove(request.OrderId, out var order))
                    {
                        _logger.LogInformation("订单记录已删除（补偿）：{OrderId}", request.OrderId);
                    }

                    await Task.CompletedTask;
                },
                retryCount: 3,
                retryInterval: 1000
            );

            if (!createOrderResult.Success)
            {
                _logger.LogError("Saga 失败: 创建订单记录失败");
                return false;
            }

            // ===== 步骤2：扣减库存 =====
            var deductStockResult = await ExecuteStepAsync(
                stepName: "DeductStock",
                executeAction: async () =>
                {
                    _logger.LogInformation("Saga Step 2: 扣减库存 - ProductId={ProductId}, Quantity={Quantity}",
                        request.ProductId, request.Quantity);

                    if (!_stocks.TryGetValue(request.ProductId, out var stock))
                    {
                        throw new Exception($"商品不存在：{request.ProductId}");
                    }

                    if (stock.Stock < request.Quantity)
                    {
                        throw new Exception($"库存不足：当前={stock.Stock}, 需要={request.Quantity}");
                    }

                    stock.Stock -= request.Quantity;
                    _logger.LogInformation("库存已扣减：ProductId={ProductId}, 剩余={Stock}",
                        request.ProductId, stock.Stock);

                    return new { ProductId = request.ProductId, Quantity = request.Quantity };
                },
                compensateAction: async (data) =>
                {
                    _logger.LogWarning("Saga Compensation 2: 恢复库存 - ProductId={ProductId}, Quantity={Quantity}",
                        request.ProductId, request.Quantity);

                    if (_stocks.TryGetValue(request.ProductId, out var stock))
                    {
                        stock.Stock += request.Quantity;
                        _logger.LogInformation("库存已恢复（补偿）：ProductId={ProductId}, 库存={Stock}",
                            request.ProductId, stock.Stock);
                    }

                    await Task.CompletedTask;
                },
                retryCount: 3,
                retryInterval: 1000
            );

            if (!deductStockResult.Success)
            {
                _logger.LogError("Saga 失败: 扣减库存失败 - {Error}",
                    deductStockResult.Exception?.Message);
                return false;
            }

            // ===== 步骤3：扣款 =====
            var deductBalanceResult = await ExecuteStepAsync(
                stepName: "DeductBalance",
                executeAction: async () =>
                {
                    _logger.LogInformation("Saga Step 3: 扣款 - UserId={UserId}, Amount={Amount}",
                        request.UserId, request.Amount);

                    if (!_accounts.TryGetValue(request.UserId, out var account))
                    {
                        throw new Exception($"账户不存在：{request.UserId}");
                    }

                    if (account.Balance < request.Amount)
                    {
                        throw new Exception($"余额不足：当前={account.Balance}, 需要={request.Amount}");
                    }

                    account.Balance -= request.Amount;
                    _logger.LogInformation("账户已扣款：UserId={UserId}, 剩余={Balance}",
                        request.UserId, account.Balance);

                    return new { UserId = request.UserId, Amount = request.Amount };
                },
                compensateAction: async (data) =>
                {
                    _logger.LogWarning("Saga Compensation 3: 退款 - UserId={UserId}, Amount={Amount}",
                        request.UserId, request.Amount);

                    if (_accounts.TryGetValue(request.UserId, out var account))
                    {
                        account.Balance += request.Amount;
                        _logger.LogInformation("账户已退款（补偿）：UserId={UserId}, 余额={Balance}",
                            request.UserId, account.Balance);
                    }

                    await Task.CompletedTask;
                },
                retryCount: 3,
                retryInterval: 1000
            );

            if (!deductBalanceResult.Success)
            {
                _logger.LogError("Saga 失败: 扣款失败 - {Error}",
                    deductBalanceResult.Exception?.Message);
                return false;
            }

            // ===== 步骤4：更新订单状态 =====
            var updateOrderResult = await ExecuteStepAsync(
                stepName: "UpdateOrderStatus",
                executeAction: async () =>
                {
                    _logger.LogInformation("Saga Step 4: 更新订单状态 - OrderId={OrderId}", request.OrderId);

                    if (_orders.TryGetValue(request.OrderId, out var order))
                    {
                        order.Status = "COMPLETED";
                        order.UpdateTime = DateTime.UtcNow;
                        _logger.LogInformation("订单状态已更新：{OrderId} -> COMPLETED", request.OrderId);
                    }

                    return new { OrderId = request.OrderId, Status = "COMPLETED" };
                },
                compensateAction: async (data) =>
                {
                    _logger.LogWarning("Saga Compensation 4: 恢复订单状态 - OrderId={OrderId}", request.OrderId);

                    if (_orders.TryGetValue(request.OrderId, out var order))
                    {
                        order.Status = "CANCELLED";
                        order.UpdateTime = DateTime.UtcNow;
                        _logger.LogInformation("订单状态已恢复（补偿）：{OrderId} -> CANCELLED", request.OrderId);
                    }

                    await Task.CompletedTask;
                },
                retryCount: 2,
                retryInterval: 500
            );

            if (!updateOrderResult.Success)
            {
                _logger.LogError("Saga 失败: 更新订单状态失败");
                return false;
            }

            _logger.LogInformation("Saga 成功: 订单创建完成 - OrderId={OrderId}", request.OrderId);
            return true;
        }
    }

    /// <summary>
    /// 创建订单 Saga 请求
    /// </summary>
    public class CreateOrderSagaRequest
    {
        public string OrderId { get; set; } = string.Empty;
        public string UserId { get; set; } = string.Empty;
        public string ProductId { get; set; } = string.Empty;
        public int Quantity { get; set; }
        public decimal Amount { get; set; }
    }

    /// <summary>
    /// 订单记录
    /// </summary>
    public class OrderRecord
    {
        public string OrderId { get; set; } = string.Empty;
        public string UserId { get; set; } = string.Empty;
        public string ProductId { get; set; } = string.Empty;
        public int Quantity { get; set; }
        public decimal Amount { get; set; }
        public string Status { get; set; } = string.Empty;
        public DateTime CreateTime { get; set; }
        public DateTime? UpdateTime { get; set; }
    }

    /// <summary>
    /// 库存记录
    /// </summary>
    public class StockRecord
    {
        public string ProductId { get; set; } = string.Empty;
        public int Stock { get; set; }
    }

    /// <summary>
    /// 账户记录
    /// </summary>
    public class AccountRecord
    {
        public string UserId { get; set; } = string.Empty;
        public decimal Balance { get; set; }
    }
}
